/*
 * HanoiGame.cpp
 *
 *  Created on: Oct 17, 2010
 *      Author: Jacob
 */
#pragma once
#include "stdafx.h"
#include "HanoiGame.h"

//Default factory for creating a Hanoi Game
HanoiGame* HanoiGame::newGameWithNumPegsAndTowers(int numberOfPegs)
{
	return new HanoiGame(numberOfPegs);
}

//Default ctor
HanoiGame::HanoiGame(int numberOfPegs)
	: turnsTaken(1), numberOfPegs(numberOfPegs)
{
	validateNumberOfPegs(numberOfPegs);
	generateTowers();
}

//Destructor
HanoiGame::~HanoiGame()
{
	cout << "\n" << "Hanoi Game Destructor Called";
	delete towers[0];
	delete towers[1];
	delete towers[2];
}

//Ensures the game has at least one peg. If not, sets number of pegs to one. 
void HanoiGame::validateNumberOfPegs(int &numberOfPegs)
{
	if (numberOfPegs < 1)
		numberOfPegs = 1;
}

//Creates the towers. 
void HanoiGame::generateTowers()
{
	ostringstream stringStream;

	towers[0] = generateStartingTower();

	for (int index = 1; index < numberOfTowers; index++)
	{
		stringStream << "Tower " << (index + 1);
		Tower* newTower = Tower::newTowerWithName(stringStream.str());
		towers[index] = newTower;
		stringStream.str("");
	}

}

//Creates the first tower
Tower* HanoiGame::generateStartingTower()
{
	Tower* leftTower = Tower::newTowerWithStartingPegsAndName(numberOfPegs,
			"Tower 1");
	return leftTower;
}

//Default game loop, accepts user input. 
void HanoiGame::play()
{
	char userInput;
	takeTurnMessage << "There are " << numberOfPegs << " Pegs, Play Game? Y/N";

	cout << this->toString();

	cout << "\n" << takeTurnMessage.str();
	cin >> userInput;
	if (userInput == 'Y' || userInput == 'y')
	{
		takeTurn();
	}
	else if (userInput == 'N' || userInput == 'n')
		return;
}

//One "step" 
void HanoiGame::takeTurn()
{
	if (numberOfPegs == 1)
	{
		towers[1]->addPeg(towers[0]->removeTopPeg());
		cout << this->toString();
		return;
	}

	solveProblem(1, 3, 2, numberOfPegs);
	cout << "\nTurns Taken " << turnsTaken << this->toString();
}

//Recursive solution to the game. 
void HanoiGame::solveProblem(int startingTower, int desinationTower,
		int extraTower, int pegCount)
{
	if (pegCount > 0)
	{
		++turnsTaken;
		solveProblem(startingTower, extraTower, desinationTower, pegCount - 1);

		cout << "\nPeg " << pegCount << " Moves from " << startingTower
				<< " to " << desinationTower;

		towers[desinationTower - 1]->addPeg(
				towers[startingTower - 1]->removeTopPeg());

		solveProblem(extraTower, desinationTower, startingTower, pegCount - 1);
	}
}

//A toString representation of the game's state. 
string HanoiGame::toString()
{
	ostringstream stringStream;

	stringStream << "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=";
	for (int index = 0; index < numberOfTowers; index++)
	{
		stringStream << towers[index]->toString();
	}
	stringStream << "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=";

	return stringStream.str();
}

